'''
**Concept of LinkedListQueue:**
LinkedListQueue is an implementation of the Queue data structure using a linked list. It follows the First-In-First-Out (FIFO) principle, where elements are added at the rear end and removed from the front end. The LinkedListQueue provides efficient operations for enqueueing, dequeueing, and accessing elements in a queue.

**Properties of LinkedListQueue:**
1. Rear Pointer: The LinkedListQueue maintains a rear pointer that points to the last node in the linked list, representing the rear end of the queue where new elements are enqueued.
2. Front Pointer: The LinkedListQueue also maintains a front pointer that points to the first node in the linked list, representing the front end of the queue where elements are dequeued.
3. Size Tracking: The LinkedListQueue keeps track of its size, representing the number of elements it currently holds.
4. Empty Condition: The LinkedListQueue is empty when no elements are present.
5. Enqueue Operation: The enqueue operation adds an element to the rear end of the queue by creating a new node and updating the rear pointer.
6. Dequeue Operation: The dequeue operation removes and returns the element from the front end of the queue by updating the front pointer and removing the corresponding node.
7. Peek Operation: The peek operation retrieves the element at the front end of the queue without removing it.
8. IsEmpty Operation: Checks if the LinkedListQueue is empty.
9. Length Operation: Returns the total number of elements in the LinkedListQueue.

**Operations of LinkedListQueue:**
1. Enqueue: Inserts an element at the rear end of the LinkedListQueue.
2. Dequeue: Removes and returns the element from the front end of the LinkedListQueue.
3. Peek: Retrieves the element at the front end of the LinkedListQueue without removing it.
4. IsEmpty: Checks if the LinkedListQueue is empty.
5. Length: Returns the total number of elements in the LinkedListQueue.

The LinkedListQueue provides an efficient way to manage elements in a queue, especially when the size of the queue may vary dynamically. It leverages the flexibility of a linked list to accommodate a variable number of elements and ensures efficient enqueue and dequeue operations. LinkedListQueue is commonly used in scenarios where the order of arrival and processing of elements is essential, such as task scheduling, message queues, and breadth-first search algorithms.
'''

class Node:
    """
    A simple implementation of a node in a linked list.

    Attributes:
        value: The value stored in the node.
        next: A reference to the next node in the linked list.
    """

    def __init__(self, value):
        self.value = value
        self.next = None


class LinkedListQueue:
    """
    A simple implementation of a linked list queue.

    This linked list queue class supports enqueue, dequeue, peek, is_empty,
    clear, size operations.

    """

    def __init__(self):
        """
        Initialize the linked list queue.
        """
        self._front = None
        self._rear = None
        self._size = 0

    def __len__(self) -> int:
        """Return the number of elements in the linked list queue."""
        return self._size

    def __repr__(self):
        """Return a string representation of the linked list queue."""
        current = self._front
        values = []
        while current:
            values.append(str(current.value))
            current = current.next
        return "LinkedListQueue(" + ", ".join(values) + ")"

    def __str__(self):
        """Return a formatted string representation of the linked list queue."""
        return repr(self)

    def enqueue(self, item: object):
        """
        Add an item to the rear of the linked list queue.

        Args:
            item (object): The item to be added.
        """
        new_node = Node(item)
        if self._rear is None:
            self._front = new_node
            self._rear = new_node
        else:
            self._rear.next = new_node
            self._rear = new_node
        self._size += 1

    def dequeue(self) -> object:
        """
        Remove and return the item from the front of the linked list queue.

        Returns:
            object: The item from the front of the linked list queue.

        Raises:
            IndexError: If the linked list queue is empty.
        """
        if self._front is None:
            raise IndexError("Linked list queue is empty")
        item = self._front.value
        self._front = self._front.next
        if self._front is None:
            self._rear = None
        self._size -= 1
        return item

    def peek(self) -> object:
        """
        Return the item from the front of the linked list queue without removing it.

        Returns:
            object: The item from the front of the linked list queue.

        Raises:
            IndexError: If the linked list queue is empty.
        """
        if self._front is None:
            raise IndexError("Linked list queue is empty")
        return self._front.value

    def is_empty(self) -> bool:
        """Check if the linked list queue is empty."""
        return self._size == 0

    def clear(self):
        """Clear all elements from the linked list queue."""
        self._front = None
        self._rear = None
        self._size = 0

    def size(self) -> int:
        """Return the current size of the linked list queue."""
        return self._size


if __name__ == "__main__":
    linked_list_queue = LinkedListQueue()  # Initialize a linked list queue

    # Enqueue elements into the linked list queue
    linked_list_queue.enqueue(3)
    linked_list_queue.enqueue(5)
    linked_list_queue.enqueue(6)
    linked_list_queue.enqueue(9)
    linked_list_queue.enqueue(10)

    print(linked_list_queue)  # Expected output: LinkedListQueue(3, 5, 6, 9, 10)
    assert len(linked_list_queue) == 5, "Expected linked list queue length to be 5"
    assert linked_list_queue.peek() == 3, "Expected item at the front of the linked list queue to be 3"

    # Dequeue an element
    item = linked_list_queue.dequeue()  # item = 3
    print(item)  # Expected output: 3

    # Peek at the front of the linked list queue
    front_item = linked_list_queue.peek()  # front_item = 5
    print(front_item)  # Expected output: 5

    print(linked_list_queue)  # Expected output: LinkedListQueue(5, 6, 9, 10)

    # Check if the linked list queue is empty
    print(linked_list_queue.is_empty())  # Expected output: False

    # Clear the linked list queue
    linked_list_queue.clear()
    print(linked_list_queue)  # Expected output: LinkedListQueue()
    print(len(linked_list_queue))  # Expected output: 0

    # Check the current size of the linked list queue
    print(linked_list_queue.size())  # Expected output: 0
